/**
 * @author 14544
 * @date 2020/4/1 14:47
 */
// WebSocket 协议提供了一种在浏览器和服务器之间建立持久连接的通信方法。
// 一旦 Websocket 连接建立，客户端和服务端就能互相发送数据了。
// WebSocket 特别适用于连续数据交换的服务，例如在线游戏，实时交易系统等等。

// 一个简单的例子
{
    // 实例化一个webSocket的实例
    // 始终使用 wss://
    // wss:// 协议不仅能加密，而且更可靠。
    // 一方面是因为 ws:// 数据不是加密的，对于任何中间人来说其数据都是可见的。另一方面是因为过去的代理服务还不知道 WebSocket，它们可能因为识别到这个“奇怪的”头而终止连接。
    // 另外，wss:// 是基于 TLS 的 WebSocket，（类似于 HTTPS 是 HTTP 基于 TLS），传输安全层（transport security layer）加密发送方的数据并在接收方解密，
    // 因此它通过代理加密传递。它们看不到传输的内容且会让这些数据通过。
    let wb = new WebSocket('ws://example.com');
    let wb2 = new WebSocket('wss://example.com');
    // 初始化后 可以监听四个生命周期钩子
    wb.onopen = function () {
        // 连接建立
        // 如果我们想要发送数据，在连接建立后使用
        wb.send({})
    }
    wb.onmessage = function () {
        // 接受数据
    }
    wb.onerror = function () {
        // 请求发生错误
    }
    wb.onclose = function () {
        // 连接关闭时
    }
}
// 一个浏览器请求的例子：new WebSocket("wss://javascript.info/chat")。 请求头中会包含以下内容:
// GET /chat
// Host: javascript.info
// Origin: https://javascript.info
// Connection: Upgrade
// Upgrade: websocket
// Sec-WebSocket-Key: Iv8io/9s+lYFgZWcXczP8Q==
// Sec-WebSocket-Version: 13

// 以下为解释:
// Origin —— 客户端页面的 origin，例如：https://javascript.info。WebSocket 对象原生支持 cross-origin。没有特殊的头与限制。以前的服务器不能处理 WebSocket，因此不存在任何兼容性问题。但是 Origin 请求头很重要，因为它允许服务器做出决定是否使用 WebSocket 与该网站通信。
// Connection: Upgrade —— 表示客户端想要更改协议。
// Upgrade: websocket —— 请求更改为“websocket”协议。
// Sec-WebSocket-Key —— 浏览器随机生成的安全密钥。
// Sec-WebSocket-Version —— WebSocket 协议版本，当前为 13。


// 如果服务器同意转换为 WebSocket 协议，服务器就会返回响应代码 101：

// 101 Switching Protocols
// Upgrade: websocket
// Connection: Upgrade
// Sec-WebSocket-Accept: hsBlbuDTkk24srzEOTBUlZAlC2g=   Sec-WebSocket-Accept 是 Sec-WebSocket-Key，使用特殊的算法重新编码。浏览器以此来确保响应正确的请求。
// 然后，数据就使用 WebSocket 协议传输，我们很快就会看到它的结构（“frames”）。它和 HTTP 有着本质上的区别。

// 关闭连接
{

    // code 是一个特殊的 WebSocket 状态码（可选）
    // reason 是一个描述关闭连接的原因的字符串（可选）
    // 然后，另外一方通过 close 事件处理器获取了状态码和关闭原因，例如：

    // 关闭方：
    socket.close(1000, "Work complete");

    // 另一方
    socket.onclose = event => {
        // event.code === 1000
        // event.reason === "Work complete"
        // event.wasClean === true（完成关闭）
    };
    //常见状态码：
    // 1000 —— 默认，正常关闭（如果没有指明 code 时使用它），
    // 1006 —— 没有办法手动指定这个值，表示连接丢失（没有 close frame）。
    // 特别是当我们尝试设置任何小于 1000 的状态码时将会出错。
}

// 要获取连接状态，可以通过 socket.readyState 属性值来获取：
// 0 —— “CONNECTING”：连接还未建立，
// 1 —— “OPEN”：通信中，
// 2 —— “CLOSING”：连接关闭中，
// 3 —— “CLOSED”：连接已关闭。


// WebSocket 是一种在浏览器和服务器之间建立持久连接的现代方式。

// WebSockets 没有跨域限制。
// 浏览器对 WebSockets 支持很好。
// 可以发送/接收字符串和二进制数据。
// WebSockets 的 API 很简单。

// WebSockets 方法：

// socket.send(data)，
// socket.close([code], [reason])。
// WebSockets 事件：

// open，
// message，
// error，
// close。
// WebSocket 自身并不包含重新连接（reconnection），身份验证（authentication）和许多其他高级机制。因此有针对于此的客户端/服务端的库，并且可以手动实现这些功能。

// 有时候，为了将 WebSocket 集成到现有项目中，人们将主 HTTP 服务与 WebSocket 服务并行运行，并且它们之间共享同一个数据库。对于 WebSocket 请求使用一个通向 WebSocket 服务器的子域 wss://ws.site.com，而 https://site.com 则转到主 HTTP 服务器。

// 当然，其他集成方式也是可行的。许多服务器（例如 Node.js）可以同时支持 HTTP 和 WebSocket 协议。

// EventSource：
/*
类似于 WebSocket，其连接是持久的。

但是两者之间也有几个重要的区别：

WebSocket	                                        EventSource
双向（Bi-directional）：客户端和服务端都能修改消息	 单向（ One-directional）：仅服务端能发送消息
二进制和文本数据	                                     仅文本数据
WebSocket 协议	                                     普通 HTTP 协议
与 WebSocket 相比，EventSource 是一种与服务器通信的低配版本。

我们为什么要使用它呢？

主要原因是：简单。在许多应用中，WebSocket 有点大材小用。

我们需要从服务器接收数据流：可能是聊天消息或者商品价格等等。这是 EventSource 擅长之处。它支持自动重新连接，而在 WebSocket 中这个功能我们要手动实现。另外，它是一个普通的我们熟知的 HTTP，而不是其他新协议。*/
